/*
 * Copyright 2012-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Import;

/**
 * Registers packages with {@link AutoConfigurationPackages}. When no {@link #basePackages
 * base packages} or {@link #basePackageClasses base package classes} are specified, the
 * package of the annotated class is registered.
 * <p>
 *      将指定的包注册到 AutoConfigurationPackages 中。
 * 		这些包会被后续用于自动扫描实体类（如 JPA 的 @Entity 类）、组件等。
 * 		如果没有显式指定包（通过 basePackages 或 basePackageClasses），那么默认注册的是标注该注解的类所在的包。
 *
 * 		和 @EnableAutoConfiguration 的关系：
 * 		@EnableAutoConfiguration 注解内部导入了 @AutoConfigurationPackage，
 * 		因此当你使用 @SpringBootApplication 或 @EnableAutoConfiguration 时，自动启用了包注册功能。
 * </p>
 *
 * 它的主要作用是将某个包注册为自动配置扫描的根包（base package），Spring Boot 会使用这个包路径去扫描实体类、组件等。
 *
 *
 * <p>
 *     🧩 四、背后的机制
 * 		1. AutoConfigurationPackages.Registrar
 * 				这是一个 ImportBeanDefinitionRegistrar 实现类，它会在 Spring 容器启动过程中被调用。
 *
 * 				主要职责：
 * 				解析 @AutoConfigurationPackage 注解中的 basePackages 或 basePackageClasses。
 * 				将解析出的包路径注册到 AutoConfigurationPackages 中。
 * 				最终这些包路径会存储在一个 BeanFactory 属性中，供其他组件（如实体扫描器）使用。
 * 		2. AutoConfigurationPackages 是什么？
 * 			是一个工具类，提供静态方法获取当前应用的自动配置包路径。
 * 			在 JPA 自动扫描实体类、数据源配置等场景中被广泛使用。
 * </p>
 *<p>
 *     详细的解析过程:
 *     spring 容器在启动过程中，识别到 @Import 注解时，会触发 ImportBeanDefinitionRegistrar 的回调。
 *     他会把注解 @AutoConfigurationPackage 的元信息传递到 AutoConfigurationPackages.Registrar 的registerBeanDefinitions。
 *     解析 basePackages 或 basePackageClasses （如果都不存在，则默认是@AutoConfigurationPackage注解注释的类所在路径），然后将解析出的包路径注册到 AutoConfigurationPackages 中。
 *     实际是注册到 bean定义名称是 AutoConfigurationPackages.class.getName()，bean的实际类型是 BasePackages，
 *     然后在 后续的容器初始化过程中，大概是 工厂后置处理器 阶段，会将这个 bean 转换成实际的包路径集合，并行扫描生成很多bean定义。
 *
 *</p>
 * @author Phillip Webb
 * @since 1.3.0
 * @see AutoConfigurationPackages
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

	/**
	 * <p>
	 *      以字符串形式指定要注册的包名。
	 * 		示例：basePackages = "com.example.demo"。
	 * 		如果不设置，默认使用当前类所在的包。
	 * </p>
	 * Base packages that should be registered with {@link AutoConfigurationPackages}.
	 * 指定需要注册到 AutoConfigurationPackages 的基础包。
	 * <p>
	 * Use {@link #basePackageClasses} for a type-safe alternative to String-based package
	 * names.
	 * 使用 {@link #basePackageClasses} 作为基于字符串的包名的类型安全的替代方案。
	 * @return the back package names
	 * @since 2.3.0
	 */
	String[] basePackages() default {};

	/**
	 * Type-safe alternative to {@link #basePackages} for specifying the packages to be
	 * registered with {@link AutoConfigurationPackages}.
	 * <p>
	 * Consider creating a special no-op marker class or interface in each package that
	 * serves no purpose other than being referenced by this attribute.
	 * @return the base package classes
	 * @since 2.3.0
	 */
	Class<?>[] basePackageClasses() default {};

}
